package com.iwomy.secureplat.platform.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.iwomy.secureplat.admin.api.entity.SysDept;
import com.iwomy.secureplat.common.core.util.R;
import com.iwomy.secureplat.common.data.datascope.DataScope;
import com.iwomy.secureplat.platform.dto.AlarmFaultLoggingDTO;
import com.iwomy.secureplat.platform.entity.*;
import com.iwomy.secureplat.platform.mapper.AlarmFaultLoggingMapper;
import com.iwomy.secureplat.platform.mapper.BasicDeviceMapper;
import com.iwomy.secureplat.platform.service.AlarmFaultLoggingService;
import com.iwomy.secureplat.platform.utils.DataScopeUtils;
import com.iwomy.secureplat.platform.utils.DeptFillUtils;
import com.iwomy.secureplat.platform.utils.RemoteDeptUtils;
import com.iwomy.secureplat.platform.vo.AlarmLoggingVO;
import com.iwomy.secureplat.platform.vo.ThreeDaysAlarmCountVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 故障报警记录表
 *
 * @author pig
 * @date 2023-12-24 15:06:44
 */
@Service
public class AlarmFaultLoggingServiceImpl extends ServiceImpl<AlarmFaultLoggingMapper, AlarmFaultLoggingEntity> implements AlarmFaultLoggingService {

	@Autowired
	private RemoteDeptUtils remoteDeptUtils;

	@Autowired
	private BasicDeviceMapper basicDeviceMapper;

	@Override
	public Page getAlarmFaultLoggingPage(Page page, AlarmFaultLoggingDTO alarmFaultLoggingDTO) {


		//查询
		MPJLambdaWrapper<AlarmFaultLoggingEntity> wrapper = new MPJLambdaWrapper<>();
		wrapper.selectAll(AlarmFaultLoggingEntity.class);
		wrapper.selectAs(BasicInstallLocationEntity::getDetailAddress, AlarmLoggingVO::getDetailAddress);
		wrapper.selectAs(BasicInstallLocationEntity::getAddress, AlarmLoggingVO::getAddress);
		wrapper.leftJoin(BasicInstallLocationEntity.class, BasicInstallLocationEntity::getId, AlarmFaultLoggingEntity::getInstallLocationId);
		wrapper.eq(ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getDeviceTypeId()),
				AlarmFaultLoggingEntity::getDeviceTypeId, alarmFaultLoggingDTO.getDeviceTypeId());
		wrapper.eq(ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getDeviceModelId()),
				AlarmFaultLoggingEntity::getDeviceModelId, alarmFaultLoggingDTO.getDeviceModelId());

		List<Long> list = DataScopeUtils.getList();
		wrapper.in(ObjectUtil.isNotEmpty(list), AlarmFaultLoggingEntity::getDeptId,
				list);
		wrapper.like(ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getImei()), AlarmFaultLoggingEntity::getImei
				, alarmFaultLoggingDTO.getImei()).orderByDesc(AlarmFaultLoggingEntity::getCreateTime);
		if (ArrayUtil.isNotEmpty(alarmFaultLoggingDTO.getCreateTime())) {
			wrapper.ge(AlarmFaultLoggingEntity::getCreateTime, alarmFaultLoggingDTO.getCreateTime()[0]).le(AlarmFaultLoggingEntity::getCreateTime,
					alarmFaultLoggingDTO.getCreateTime()[1]);
		}

		wrapper.eq(ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getEventTypeId()),
				AlarmFaultLoggingEntity::getEventTypeId, alarmFaultLoggingDTO.getEventTypeId());

		wrapper.eq(ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getInstallLocationId()),
				AlarmFaultLoggingEntity::getInstallLocationId, alarmFaultLoggingDTO.getInstallLocationId());

		wrapper.eq(ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getState()), AlarmFaultLoggingEntity::getState,
				alarmFaultLoggingDTO.getState());
		wrapper.eq(StrUtil.isNotEmpty(alarmFaultLoggingDTO.getEventTypeName()),AlarmFaultLoggingEntity::getEventTypeName,alarmFaultLoggingDTO.getEventTypeName());

		if (ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getBindState())) {
			LambdaQueryWrapper<BasicDeviceEntity> basicDeviceWrapper = new LambdaQueryWrapper<>();
			basicDeviceWrapper.in(BasicDeviceEntity::getBindState, alarmFaultLoggingDTO.getBindState());
			List<BasicDeviceEntity> deviceList = basicDeviceMapper.selectList(basicDeviceWrapper);
			List<Long> deviceIds = deviceList.stream().map(BasicDeviceEntity::getId).collect(Collectors.toList());
			if (!deviceIds.isEmpty()) {
				wrapper.in(AlarmFaultLoggingEntity::getDeviceId, deviceIds);
			} else {
				wrapper.eq(AlarmFaultLoggingEntity::getDeviceId, deviceIds);
			}
		}

		if (ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getDeptLimit())) {
			if (alarmFaultLoggingDTO.getDeptLimit() == 20) {
				wrapper.in(AlarmFaultLoggingEntity::getDeptId, alarmFaultLoggingDTO.getDeptId());
			} else {
				List<SysDept> deptList = (List<SysDept>) remoteDeptUtils.getDescendantList(alarmFaultLoggingDTO.getDeptId()).getData();
				List<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList());
				if (deptIds != null) wrapper.in(AlarmFaultLoggingEntity::getDeptId, deptIds);
			}
		} else {
			if (ObjectUtil.isNotEmpty(alarmFaultLoggingDTO.getDeptId())) {
				wrapper.in(AlarmFaultLoggingEntity::getDeptId, alarmFaultLoggingDTO.getDeptId());
			}
		}

		page = this.getBaseMapper().selectJoinPage(page, AlarmLoggingVO.class, wrapper);
		DeptFillUtils.fill(page);
		return page;
	}

	@Override
	public long selectCountByImei(String imei) {
		return count(Wrappers.lambdaQuery(AlarmFaultLoggingEntity.class).eq(AlarmFaultLoggingEntity::getImei, imei)
				.eq(AlarmFaultLoggingEntity::getState, 20));
	}

	@Override
	public AlarmFaultLoggingEntity oneByImeiDesc(String imei) {
		return getOne(Wrappers.lambdaQuery(AlarmFaultLoggingEntity.class).eq(AlarmFaultLoggingEntity::getImei, imei)
				.eq(AlarmFaultLoggingEntity::getState, 20)
				.orderByDesc(AlarmFaultLoggingEntity::getCreateTime).last("limit 1"));
	}

    @Override
    public List<AlarmFaultLoggingEntity> listByScope(LambdaQueryWrapper<AlarmFaultLoggingEntity> wrapper, DataScope dataScope) {
		List<AlarmFaultLoggingEntity> list = this.getBaseMapper().selectListByScope(wrapper,dataScope);
		return list;
    }

	@Override
	public R threeDaysFaultCount() {
		LambdaQueryWrapper<AlarmFaultLoggingEntity> wrapper = Wrappers.lambdaQuery();
		List<AlarmFaultLoggingEntity> list = this.baseMapper.selectListByScope(wrapper, new DataScope());
		List<Long> alarmFaultId = list.stream().map(AlarmFaultLoggingEntity::getId).collect(Collectors.toList());

		ThreeDaysAlarmCountVO threeDaysAlarmCountVO = new ThreeDaysAlarmCountVO();
		if (ObjectUtil.isNotEmpty(alarmFaultId)) {
			LocalDateTime now = LocalDateTime.now();
			LocalDateTime threeDaysBefore = now.minusHours(72);
			LambdaQueryWrapper<AlarmFaultLoggingEntity> queryWrapper = Wrappers.lambdaQuery();
			queryWrapper.between(AlarmFaultLoggingEntity::getCreateTime, threeDaysBefore, now); // 报警时间在近 3 天内
			queryWrapper.in(AlarmFaultLoggingEntity::getId, alarmFaultId);
			List<AlarmFaultLoggingEntity> faultRecordList = this.getBaseMapper().selectList(queryWrapper);
			// 已处理的记录数
			long handledCount = faultRecordList.stream()
					.filter(record -> record.getState() == 10)
					.count();
			// 未处理的记录数
			long unhandledCount = faultRecordList.stream()
					.filter(record -> record.getState() == 20)
					.count();
			threeDaysAlarmCountVO.setThreeDaysFaultCount((long)faultRecordList.size());
			threeDaysAlarmCountVO.setFaultHandledCount(handledCount);
			threeDaysAlarmCountVO.setFaultUnhandledCount(unhandledCount);

		}
		return R.ok(threeDaysAlarmCountVO);
	}

	@Override
	public long countByScope(LambdaQueryWrapper<AlarmFaultLoggingEntity> wrapper, DataScope dataScope) {
		return this.getBaseMapper().selectCount(wrapper);
	}

}